package com.jingdianjichi.subject.application.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.jingdianjichi.subject.application.convert.SubjectCategoryDTOConverter;
import com.jingdianjichi.subject.application.convert.SubjectInfoDTOConverter;
import com.jingdianjichi.subject.application.convert.SubjectLabelDTOConverter;
import com.jingdianjichi.subject.application.convert.SubjectLikedDTOConverter;
import com.jingdianjichi.subject.application.dto.SubjectCategoryDTO;
import com.jingdianjichi.subject.application.dto.SubjectInfoDTO;
import com.jingdianjichi.subject.application.dto.SubjectLabelDTO;
import com.jingdianjichi.subject.application.dto.SubjectLikedDTO;
import com.jingdianjichi.subject.common.entity.PageResult;
import com.jingdianjichi.subject.common.utils.LoginUtil;
import com.jingdianjichi.subject.common.entity.Result;
import com.jingdianjichi.subject.domain.entity.SubjectCategoryBO;
import com.jingdianjichi.subject.domain.entity.SubjectInfoBO;
import com.jingdianjichi.subject.domain.entity.SubjectLikedBO;
import com.jingdianjichi.subject.domain.service.SubjectCategoryDomainService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/subject/category")
@Slf4j          //log4j2配合我们的@Slf4j就行了,加上这个注解就会有一个log的对象
public class SubjectCategoryController {

    @Resource
    private SubjectCategoryDomainService subjectCategoryDomainService;

    /**
     * 添加分类,包括大分类和小分类的
     */
    @PostMapping("/add")
    public Result<Boolean> add(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        //左逻辑判断
        try {
            if (log.isInfoEnabled()){       //这里就是如果是info级别的日志才回去打印的,高并发的情况下,是先处理JSON转换的,如果我们判断一下就可以避免不必的浪费
                log.info("SubjectCategoryController.add.dto:{}", JSON.toJSONString(subjectCategoryDTO));
            }

            //入参判断,你也可以使用JSR303,就和断言差不多的,如果错的话就会抛出异常的,之后我们也会去升级的,JSR303,全局异常拦截处理的
            /*
                这个是guava的方式
             */
            Preconditions.checkNotNull(subjectCategoryDTO.getCategoryType(),"分类类型不能是空的");
            //Preconditions.checkArgument(!StringUtils.isEmpty(subjectCategoryDTO.getCategoryName()),"分类名称不能是空的");  //文字不能是空的
            Preconditions.checkArgument(!StringUtils.isBlank(subjectCategoryDTO.getCategoryName()),"分类名称不能是空的");  //用这个工具类

            Preconditions.checkNotNull(subjectCategoryDTO.getParentId(),"分类父id不能是空的");

            //转换对象
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            subjectCategoryDomainService.add(subjectCategoryBO);

            return Result.ok(true);
        }catch (Exception e){
            log.error("SubjectCategoryController.add.error:{}",e.getMessage(),e);

            return Result.fail(e.getMessage());
        }
    }

    /**
     *查询分类
     *  大类
     */
    @PostMapping("/queryPrimaryCategory")
    public Result<List<SubjectCategoryDTO>> queryPrimaryCategory(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        try {
            /*
                空的,和下面公用一个接口了
                SubjectCategoryBO subjectCategoryBO = new SubjectCategoryBO();
                subjectCategoryBO.setCategoryType(CategoryTypeEnum.PRIMARY.getCode());   这个前端直接传递过来
             */

            if (log.isInfoEnabled()){       //这里就是如果是info级别的日志才回去打印的,高并发的情况下,是先处理JSON转换的,如果我们判断一下就可以避免不必的浪费
                log.info("SubjectCategoryController.queryPrimaryCategory.dto:{}", JSON.toJSONString(subjectCategoryDTO));
            }

            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategory(subjectCategoryBO);

            //转换
            List<SubjectCategoryDTO> dtoList = SubjectCategoryDTOConverter.INSTANCE.convertBotoCategoryDTOlist(subjectCategoryBOList);

            //返回数据
            return Result.ok(dtoList);
        }catch (Exception e){
            log.error("SubjectCategoryController.queryPrimaryCategory.error:{}",e.getMessage(),e);
            return Result.fail("查询失败");
        }
    }


    /**
     * 查询大类下分类的
     */
    @PostMapping("/queryCategoryByPrimary")
    public Result<List<SubjectCategoryDTO>> queryCategoryByPrimary(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        try {
            if (log.isInfoEnabled()){
                log.info("SubjectCategoryController.queryCategoryByPrimary.dto:{}",JSON.toJSONString(subjectCategoryDTO));
            }

            //参数判断,id不能是空的
            Preconditions.checkNotNull(subjectCategoryDTO.getParentId(),"父id不能是空的");

            //转换
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategory(subjectCategoryBO);

            //转换
            List<SubjectCategoryDTO> dtoList = SubjectCategoryDTOConverter.INSTANCE.convertBotoCategoryDTOlist(subjectCategoryBOList);

            //返回数据
            return Result.ok(dtoList);
        }catch (Exception e){
            log.error("SubjectCategoryController.queryPrimaryCategory.error:{}",e.getMessage(),e);
            return Result.fail("查询失败");
        }
    }


    /**
     * 更新分类
     */
    @PostMapping("/update")
    public Result<Boolean> update(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        try {
            if (log.isInfoEnabled()){
                log.info("SubjectCategoryController.update.dto:{}",JSON.toJSONString(subjectCategoryDTO));
            }

            //参数判断,id不能是空的
            Preconditions.checkNotNull(subjectCategoryDTO.getId(),"id不能是空的");

            //转换
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            //更新分类
            Boolean result= subjectCategoryDomainService.update(subjectCategoryBO);

            //返回数据
            return Result.ok(result);
        }catch (Exception e){
            log.error("SubjectCategoryController.update.error:{}",e.getMessage(),e);
            return Result.fail("更新分类失败");
        }
    }


    /**
     * 删除分类
     */
    @PostMapping("/delete")
    public Result<Boolean> delete(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        try {
            if (log.isInfoEnabled()){
                log.info("SubjectCategoryController.delete.dto:{}",JSON.toJSONString(subjectCategoryDTO));
            }

            //参数判断,id不能是空的
            Preconditions.checkNotNull(subjectCategoryDTO.getId(),"id不能是空的");

            //转换
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            //更新分类
            Boolean result= subjectCategoryDomainService.delete(subjectCategoryBO);

            //返回数据
            return Result.ok(result);
        }catch (Exception e){
            log.error("SubjectCategoryController.delete.error:{}",e.getMessage(),e);
            return Result.fail("删除分类失败");
        }
    }



    /**
     * 查询大类下类及标签,我们之前是大类查小类,小类去轮训标签,我们这次一次性查出来给他,之前我们是通过,cateGoryType=1 或者2 来查询的,这里我们用id来查亲
     */
    @PostMapping("/queryCategoryAndLabel")
    public Result<List<SubjectCategoryDTO>> queryCategoryAndLabel(@RequestBody SubjectCategoryDTO subjectCategoryDTO){
        try {
            //String loginId = LoginUtil.getLoginId(); 我们后面用全局拦截去做

            if (log.isInfoEnabled()){
                log.info("SubjectCategoryController.queryCategoryAndLabel.dto:{}",JSON.toJSONString(subjectCategoryDTO));
            }

            //参数判断,id不能是空的
            Preconditions.checkNotNull(subjectCategoryDTO.getId(),"分类id不能是空的");     //这里的一定要传递大类的亲,后端比如说

            //转换
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConverter.INSTANCE.convertDTOtoCategoryBO(subjectCategoryDTO);

            //一期方法
            //List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategoryAndLabel1_0(subjectCategoryBO);

            //这里我们用多线程去查询了,更新一下方法
            //List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategoryAndLabel2_0(subjectCategoryBO);

            //使用更加新的线程池实现亲
            //List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategoryAndLabel2_1(subjectCategoryBO);

            //在升级成本地缓存来做亲
            List<SubjectCategoryBO> subjectCategoryBOList= subjectCategoryDomainService.queryCategoryAndLabel2_2(subjectCategoryBO);

            //存放标签的亲
            List<SubjectCategoryDTO> dtoList=new ArrayList<>();

            //不断赋值,因为bo的东西是映射不到DTO的因为属性名字是不同的亲
            subjectCategoryBOList.forEach(bo -> {
                SubjectCategoryDTO categoryDTO=SubjectCategoryDTOConverter.INSTANCE.convertBoToDto(bo);

                List<SubjectLabelDTO> labelDTOList = SubjectLabelDTOConverter.INSTANCE.convertBOLabelDTOList(bo.getLabelBOList());

                categoryDTO.setLabelDTOList(labelDTOList);

                dtoList.add(categoryDTO);
            });

            //返回数据
            return Result.ok(dtoList);
        }catch (Exception e){
            log.error("SubjectCategoryController.queryCategoryAndLabel.error:{}",e.getMessage(),e);
            return Result.fail("查询失败");
        }
    }
}
